package com.tuling.netty.handler;

import com.tuling.netty.command.CmdProtocol;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.net.SocketAddress;
import java.util.List;

@Slf4j
public class CommandDecoder extends ByteToMessageDecoder {
    // 最小可读长度, 为什么是4?? 因为编码器 使用前4个byte作为数据长度的标识.
    private static final int MIN_READABLE_BYTE_LENGTH = 4;
    private int length = 0;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        SocketAddress socketAddress = ctx.channel().localAddress();
        log.info("地址{}", socketAddress);
        // 先读取缓冲区中可读数据长度.
        int readableBytes = in.readableBytes();

        // 如果可度数据长度大于4, 因为只有可度数据长度大于4了 才有可能出现数据传输完成的情况
        if (readableBytes > MIN_READABLE_BYTE_LENGTH) {
            if (length == 0) {
                // 读取出数据的实际长度, 这个实际长度是在编码器时设置的实际命令数据长度.
                length = in.readInt();
            }

            // 此处进行二次判断, 判断目前可读长度是否小于实际长度.
            // 如果判断成立, 那么就说明, 明前数据尚未传输完成. 我们目前不需要处理,带完成后再去进行处理
            if (readableBytes < length) {
                log.debug("当前可读数据不够, 期望:{},实际:{}", length, readableBytes);
                return;
            }

            // 如果可读长度已经大于了实际长度, 说明数据传输完成. 我们开始处理通信命令
            byte[] bytes = new byte[length];
            in.readBytes(bytes);

            // 将byte[] 反序列化为命令
            CmdProtocol protocol = com.tuling.protostuff.ProtostuffUtils.deserialize(bytes, CmdProtocol.class);
            out.add(protocol.getCmd());

            length = 0;
        }
    }
}